package com.phychips.rcp;

import com.phychips.common.*;
import com.phychips.common.ReaderIo.logType;

import android.util.Log;

public class RcpResponse
{
    public enum targetType
    {
	PR9000, PR9200
    }

    private targetType mTarget = null;
    final int ADC_ARRAY_LEN = 10;
    final int ADC_INIT = -1;
    int[] adcArray = new int[ADC_ARRAY_LEN];

    public RcpResponse(targetType target)
    {
	mTarget = target;
	adcArray[0] = ADC_INIT;
    }

    public OnBytesAvailableListener getOnBytesAvailableListener()
    {
	return mListener;
    } // End OnBytesAvailableListener()

    public iRcpEvent2 mRcpEvent2 = null;

    public void setRcpEvent(iRcpEvent2 e)
    {
	mRcpEvent2 = e;
    }
    
    private int getPcEpcLength(int pcMsb)
    {
	int length = ((pcMsb >> 2) & 0xFE) + 2;
	
	return length;
    }
    
    public void parse9200RxData(int[] rcv)
    {
	int paylord_length = (((int) rcv[3] & 0xff) << 8)
		| ((int) rcv[4] & 0xff);
	byte cmd = (byte) rcv[2];
	
	int[] dest = new int[paylord_length];
	System.arraycopy(rcv, 5, dest, 0, paylord_length);

	switch (cmd)
	{
	case RcpConst.RCP_CMD_GET_RD_INFO:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onReaderInfoReceived(dest);
	    }	    
	    break;
	case RcpConst.RCP_CMD_READ_C_UII:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onTagReceived(dest);
	    }
	    break;
	case RcpConst.RCP_CMD_READ_C_UII_TID:    
	    if(mRcpEvent2 != null)
	    {
		//if(dest[0]==0x00) break;
		if(dest.length == 1) break;
		
		int pcEpcLength = getPcEpcLength(dest[0]);
	
		int[] pcEpc = new int[pcEpcLength];
		int[] tid = new int[dest.length-pcEpcLength];
		
		System.arraycopy(dest, 0, pcEpc, 0, pcEpc.length);
		System.arraycopy(dest, pcEpc.length, tid, 0, tid.length);

		mRcpEvent2.onTagWithTidReceived(pcEpc, tid);
	    }
	    break;
	case RcpConst.RCP_CMD_READ_C_EX2:
	    if(mRcpEvent2 != null)
	    {
		System.out.println("1. dest = " + dest[0]);
		if(dest.length < 3) break;
		
		int offset = 3;
		int pcEpcLength = getPcEpcLength(dest[offset]);
	
		int[] pcEpc = new int[pcEpcLength];
		int[] tid = new int[dest.length- pcEpcLength - offset];
		
		System.arraycopy(dest, offset, pcEpc, 0, pcEpc.length);
		System.arraycopy(dest, offset + pcEpc.length, tid, 0, tid.length);

		mRcpEvent2.onTagWithTidReceived(pcEpc, tid);
	    }
	    break;
	case RcpConst.RCP_CMD_READ_C_UII_RSSI:
    	{
    	    int dataLen = paylord_length;
    	    int rssi_i = dest[dataLen - 4] & 0xff;
    	    int rssi_q = dest[dataLen - 3] & 0xff;
    	    int gain_i = dest[dataLen - 2] & 0xff;
    	    int gain_q = dest[dataLen - 1] & 0xff;
    
    	    double rfin_i = (20 * Math.log10(rssi_i) - gain_i - 33 - 30);
    	    double rfin_q = (20 * Math.log10(rssi_q) - gain_q - 33 - 30);
    
    	    rfin_i = Math.pow(10, (rfin_i / 20));
    	    rfin_q = Math.pow(10, (rfin_q / 20));
    
    	    final int rssi = (int) (20 * Math.log10(Math.sqrt(Math.pow(rfin_i,
    		    2) + Math.pow(rfin_q, 2))));
    
    	    int[] newDest = new int[paylord_length - 4];
    	    System.arraycopy(dest, 0, newDest, 0, paylord_length - 4);
    
    	    if(mRcpEvent2 != null)
    	    {
    		mRcpEvent2.onTagWithRssiReceived(newDest, rssi);
    	    }
    	}
	    break;
	case RcpConst.RCP_CMD_AUTHENTICATE:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);		
	    }
	    
	    break;
	case RcpConst.RCP_CMD_AUTHENTICATE_EX:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);		
	    }
	    
	    break;
	case RcpConst.RCP_CMD_GET_REGION:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onRegionReceived(dest[0]);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_C_SEL_PARAM:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSelectParamReceived(dest);
	    }
	    
	    break;
	case RcpConst.RCP_CMD_GET_C_QRY_PARAM:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onQueryParamReceived(dest);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_CH:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onChannelReceived(dest[0],dest[1]);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_FH_LBT:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onFhLbtReceived(dest);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_TX_PWR:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onTxPowerLevelReceived(dest[0]);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_BEEP:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	case RcpConst.RCP_CMD_READ_C_DT:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onTagMemoryReceived(dest);
	    }
	    break;
	case RcpConst.RCP_CMD_GET_HOPPING_TBL:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }	    
	    break;
	case RcpConst.RCP_CMD_GET_MODULATION:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }	    
	    break;
	case RcpConst.RCP_CMD_GET_ANTICOL_MODE:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }	    
	    break;
	case RcpConst.RCP_CMD_GET_TEMPERATURE:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }	    
	    break;
	case RcpConst.RCP_CMD_GET_RSSI:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	case RcpConst.RCP_GET_REGISTRY_ITEM:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	case RcpConst.RCP_CMD_CTL_RESET:
	    if(mRcpEvent2 != null)
	    {
		adcArray[0] = ADC_INIT;
		mRcpEvent2.onResetReceived();
	    }	    
	    break;
	case RcpConst.RCP_BATTERY_RES:
	{
            int minLevel = 255;
            int maxLevel = 0;
            int sumLevel = 0;
	    
            if(adcArray[0] == ADC_INIT)
            {
                for(int i = 0; i < ADC_ARRAY_LEN; i++)
                {
                    adcArray[i] = dest[0] & 0xff;
                }
            }
            
            for(int i = 0; i < ADC_ARRAY_LEN - 1; i++)
            {
                adcArray[i] = adcArray[i + 1];
                sumLevel += adcArray[i];
            }
            adcArray[ADC_ARRAY_LEN - 1] = dest[0] & 0xff;
            sumLevel += dest[0] & 0xff;
            
            for(int i = 0; i < ADC_ARRAY_LEN; i++)
            {
                if(minLevel > adcArray[i])
                    minLevel = adcArray[i];
                if(maxLevel < adcArray[i])
                    maxLevel = adcArray[i];
            }
            
            //System.out.println("dest" + dest[0] + "," + minLevel + "," + maxLevel);            
            sumLevel -= minLevel;
            sumLevel -= maxLevel;
            sumLevel = sumLevel >> 3;
            
            dest[0] = sumLevel & 0xff;            
            //System.out.println("dest" + dest[0] + "," + dest[1] + "," + dest[2]);
            
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onBatteryStateReceived(dest);
	    }	    
	}
	    break;
	case RcpConst.RCP_CMD_FER_TEST:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	case RcpConst.RCP_CMD_READ_C_DT_EX:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onTagMemoryLongReceived(dest);
	    }	    
	    break;
	case RcpConst.RCP_CMD_GET_SESSION:	    
	    if(mRcpEvent2 != null)
	    {	
		mRcpEvent2.onSessionReceived(dest[0]);
	    }	    
	    break;
	case RcpConst.RCP_CMD_SET_BEEP:
	case RcpConst.RCP_CMD_STOP_AUTO_READ_EX:
	case RcpConst.RCP_CMD_SET_REGION:
	case RcpConst.RCP_CMD_SET_C_SEL_PARAM:
	case RcpConst.RCP_CMD_SET_C_QRY_PARAM:
	case RcpConst.RCP_CMD_SET_CH:
	case RcpConst.RCP_CMD_SET_FH_LBT:
	case RcpConst.RCP_CMD_SET_TX_PWR:
	case RcpConst.RCP_CMD_CTL_CW:
	case RcpConst.RCP_CMD_SET_HOPPING_TBL:
	case RcpConst.RCP_CMD_SET_MODULATION:
	case RcpConst.RCP_CMD_SET_ANTICOL_MODE:
	case RcpConst.RCP_CMD_WRITE_C_DT:
	case RcpConst.RCP_CMD_BLOCKERASE_C_DT:
	case RcpConst.RCP_CMD_BLOCKWRITE_C_DT:
	case RcpConst.RCP_CMD_UNTRACEABLE:
	case RcpConst.RCP_CMD_UNTRACEABLE_EX:
	case RcpConst.RCP_CMD_READSIGNATURE:
	case RcpConst.RCP_CMD_KILL_RECOM_C:
	case RcpConst.RCP_CMD_LOCK_C:
	case RcpConst.RCP_UPDATE_REGISTRY:
	case RcpConst.RCP_ERASE_REGISTRY:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	case RcpConst.COMMAND_FAIL:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onFailureReceived(dest);
	    }
	    break;
	default:
	    if(mRcpEvent2 != null)
	    {
		mRcpEvent2.onSuccessReceived(dest, cmd);
	    }
	    break;
	}
    }

    private OnBytesAvailableListener mListener = new OnBytesAvailableListener()
    {
	@Override
	public void onBytesAvailable(byte[] rxData)
	{
	    int[] rcv = new int[rxData.length];

	    for (int i = 0; i < rcv.length; i++)
	    {
		byte temp = (Byte) rxData[i];
		rcv[i] = (int) temp;
	    }

	    if (mTarget != targetType.PR9000)
	    {
		if (!RcpLib.Chk_CRC(rcv))
		{
		    Log.i("RCPRsp", "crc_error");
		    return;
		}
	    }

	    try
	    {
		ReaderIo.log_write(logType.RSP, rxData);
	    }
	    catch (Exception e)
	    {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }

	    switch (mTarget)
	    {
	    	default:
	    	    parse9200RxData(rcv);
	    	    break;
	    }
	}
    };
} // End class
